package com.tbit.uqbike.client.service.impl;

import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import com.tbit.uqbike.client.constant.BrandRemoteConfigConstant;
import com.tbit.uqbike.client.constant.MachineStateConstant;
import com.tbit.uqbike.client.dao.capital.RideLogDetailsDao;
import com.tbit.uqbike.client.dao.core.BrandRemoteConfigDao;
import com.tbit.uqbike.client.dao.core.MachineDao;
import com.tbit.uqbike.client.dao.core.RideLogDao;
import com.tbit.uqbike.client.dto.LowCarbonDTO;
import com.tbit.uqbike.client.dto.RideLogDetailsDTO;
import com.tbit.uqbike.client.pojo.*;
import com.tbit.uqbike.client.service.BrandConfigService;
import com.tbit.uqbike.client.service.CacheService;
import com.tbit.uqbike.client.service.LowCarbonService;
import com.tbit.uqbike.client.util.Assert;
import com.tbit.uqbike.client.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class LowCarbonServiceImpl implements LowCarbonService {


    @Autowired
    private RideLogDao rideLogDao;
    @Autowired
    private RideLogDetailsDao rideLogDetailsDao;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private BrandRemoteConfigDao brandRemoteConfigDao;

    /**
     * @description: 获取当前订单的低碳骑行数据
     * @author: mo.shanyong
     * @date: 2025/5/17 15:19
     * @param: orderNO 订单编号
     * @return: com.tbit.uqbike.client.dto.LowCarbonDTO
     */
    @Override
    public LowCarbonDTO getLowCarbonInfoByOrderNO(String orderNO) {
        RideLog rideLog = rideLogDao.getByOrderNO(orderNO);
        Assert.notNull(rideLog,"-1","订单不存在");
        Machine machine = machineDao.getByMachineId(rideLog.getMachineId());
        List<BrandRemoteConfig> brandRemoteConfigList = brandRemoteConfigDao.getByAccountIdAndTypes(cacheService.getBrandId(rideLog.getAccountId()),
                Objects.equals(machine.getMachineType(), MachineStateConstant.MACHINE_TYPE_BIKE) ? new ArrayList<>(Arrays.asList(BrandRemoteConfigConstant.BIKE_CARBON, BrandRemoteConfigConstant.BIKE_CALORIE)) :
                        new ArrayList<>(Arrays.asList(BrandRemoteConfigConstant.ELECTRIC_BIKE_CARBON, BrandRemoteConfigConstant.ELECTRIC_BIKE_CALORIE))).stream().filter(brandRemoteConfig -> {
                            return StringUtils.isNotBlank(brandRemoteConfig.getParamKV());
        }).collect(Collectors.toList());
        LowCarbonDTO lowCarbonDTO = new LowCarbonDTO();
        if (CollectionUtils.isEmpty(brandRemoteConfigList)){
            return lowCarbonDTO;
        }
        Map<Integer, String> map = brandRemoteConfigList.stream().collect(Collectors.toMap(BrandRemoteConfig::getConfigType, BrandRemoteConfig::getParamKV));
        //碳排放
        double mileage = Objects.nonNull(rideLog.getMileage()) ? BigDecimal.valueOf(rideLog.getMileage()).setScale(2,RoundingMode.HALF_UP).doubleValue() : 0;

        double carbon = this.countByType(map, Objects.equals(machine.getMachineType(), MachineStateConstant.MACHINE_TYPE_BIKE) ?
                        BrandRemoteConfigConstant.BIKE_CARBON : BrandRemoteConfigConstant.ELECTRIC_BIKE_CARBON, mileage);
        lowCarbonDTO.setCarbonNum(new BigDecimal(carbon).setScale(2, RoundingMode.HALF_UP).doubleValue());
        //卡路里
        double calorie = this.countByType(map, Objects.equals(machine.getMachineType(), MachineStateConstant.MACHINE_TYPE_BIKE) ?
                        BrandRemoteConfigConstant.BIKE_CALORIE : BrandRemoteConfigConstant.ELECTRIC_BIKE_CALORIE,mileage);
        lowCarbonDTO.setCalorieNum(new BigDecimal(calorie).setScale(2, RoundingMode.HALF_UP).doubleValue());
        log.info("getLowCarbonInfoByOrderNO------->mileage:{},lowCarbonDTO:{}",mileage,JSON.toJSONString(lowCarbonDTO));
        return lowCarbonDTO;
    }

    /**
     * @description: 根据时间区间获取用户的低碳骑行数据
     * @author: mo.shanyong
     * @date: 2025/5/17 15:20
     * @param: startTime 开始时间
     * @param: endTime 结束时间
     * @return: com.tbit.uqbike.client.dto.LowCarbonDTO
     */
    @Override
    public LowCarbonDTO getLowCarbonInfoByTime(User user, String startTime, String endTime) {
        List<RideLogDetailsDTO> rideLogDetailsDTOList = rideLogDetailsDao.getByUserIdAndTime(user.getUserId(), startTime, endTime);
        LowCarbonDTO lowCarbonDTO = new LowCarbonDTO();
        if (CollectionUtils.isEmpty(rideLogDetailsDTOList)){
            return lowCarbonDTO;
        }
        List<BrandRemoteConfig> brandRemoteConfigList = brandRemoteConfigDao.getByAccountIdAndTypes(user.getAccountId(),
                new ArrayList<>(Arrays.asList(BrandRemoteConfigConstant.BIKE_CARBON, BrandRemoteConfigConstant.BIKE_CALORIE,
                BrandRemoteConfigConstant.ELECTRIC_BIKE_CARBON, BrandRemoteConfigConstant.ELECTRIC_BIKE_CALORIE))).stream().filter(brandRemoteConfig -> {
            return StringUtils.isNotBlank(brandRemoteConfig.getParamKV());
        }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(brandRemoteConfigList)){
            return lowCarbonDTO;
        }

        lowCarbonDTO.setRideTime(BigDecimal.valueOf((double) rideLogDetailsDTOList.stream().mapToInt(RideLogDetailsDTO::getRideTime).sum() / 3600).setScale(2, RoundingMode.HALF_UP).doubleValue());
        lowCarbonDTO.setRideMileage(BigDecimal.valueOf((double) rideLogDetailsDTOList.stream().mapToInt(RideLogDetailsDTO::getMileage).sum() / 1000).setScale(2, RoundingMode.HALF_UP).doubleValue());
        if (CollectionUtils.isEmpty(brandRemoteConfigList)){
            return lowCarbonDTO;
        }
        Map<Integer, String> map = brandRemoteConfigList.stream().collect(Collectors.toMap(BrandRemoteConfig::getConfigType, BrandRemoteConfig::getParamKV));
        //获取订单对应车辆对应的类型集合
        Map<Integer, Integer> machineTypeMap = this.getMachineTypeMap(rideLogDetailsDTOList);
        //计算碳排放、卡路里
        this.countAllRideLog(rideLogDetailsDTOList,machineTypeMap,map,lowCarbonDTO);
        return lowCarbonDTO;
    }
    /**
     * @description: 计算碳排放、卡路里
     * @author: mo.shanyong
     * @date: 2025/5/17 15:48
     * @param: map
     * @param: configType
     * @param: mileage
     * @return: double
     */
    private double countByType(Map<Integer, String> map,Integer configType,double mileage){
        String value = map.get(configType);
        if (StringUtils.isBlank(value)){
            return 0;
        }
        String[] split = value.split("=");
        if (split.length < 2 || StringUtils.isBlank(split[1])){
            return 0;
        }
        double unit = Double.parseDouble(split[1]);
        return mileage * unit;
    }

    /**
     * @description: 获取订单对应车辆的类型集合
     * @author: mo.shanyong
     * @date: 2025/5/17 16:42
     * @param: rideLogDetailsDTOList
     * @return: java.util.Map<java.lang.Integer, java.lang.Integer>
     */
    private Map<Integer,Integer> getMachineTypeMap(List<RideLogDetailsDTO> rideLogDetailsDTOList){
        List<Integer> machineIdList = rideLogDetailsDTOList.stream().map(RideLogDetailsDTO::getMachineId).distinct().collect(Collectors.toList());
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("machineIds", StringUtil.getListString(machineIdList));
        List<Machine> machineList = machineDao.getByMachineIds(params);
        if (CollectionUtils.isEmpty(machineList)){
            return new HashMap<>();
        }
        return machineList.stream().collect(Collectors.toMap(Machine::getMachineId,Machine::getMachineType));
    }

    /**
     * @description: 计算所有订单的碳排放、卡路里
     * @author: mo.shanyong
     * @date: 2025/5/17 16:48
     * @param: rideLogDetailsDTOList
     * @param: machineTypeMap
     */
    private void countAllRideLog(List<RideLogDetailsDTO> rideLogDetailsDTOList,Map<Integer, Integer> machineTypeMap,Map<Integer, String> map,LowCarbonDTO lowCarbonDTO){
        //自行车骑行里程数
        double bikeMileage = 0d;
        //电动车骑行里程数
        for (RideLogDetailsDTO rideLogDetailsDTO : rideLogDetailsDTOList) {
            Integer machineType = machineTypeMap.get(rideLogDetailsDTO.getMachineId());
            if (Objects.equals(machineType, MachineStateConstant.MACHINE_TYPE_BIKE)){//自行车
                bikeMileage += rideLogDetailsDTO.getMileage();
            }
        }
        //自行车
        //碳排放
        bikeMileage = new BigDecimal(bikeMileage / 1000).setScale(2,RoundingMode.HALF_UP).doubleValue();
        double electricBikeMileage = new BigDecimal(lowCarbonDTO.getRideMileage() - bikeMileage).setScale(2,RoundingMode.HALF_UP).doubleValue();
        double bikeCarbon = this.countByType(map, BrandRemoteConfigConstant.BIKE_CARBON, bikeMileage);
        //卡路里
        double bikeCalorie = this.countByType(map, BrandRemoteConfigConstant.BIKE_CALORIE, bikeMileage);
        //电动车
        //碳排放
        double electricBikeCarbon = this.countByType(map, BrandRemoteConfigConstant.ELECTRIC_BIKE_CARBON, electricBikeMileage);
        //卡路里
        double electricBikeCalorie = this.countByType(map, BrandRemoteConfigConstant.ELECTRIC_BIKE_CALORIE, electricBikeMileage);
        //碳排放
        lowCarbonDTO.setCarbonNum((bikeCarbon + electricBikeCarbon) <= 0 ? 0 :
                new BigDecimal(bikeCarbon + electricBikeCarbon).setScale(2, RoundingMode.HALF_UP).doubleValue());
        //卡路里
        lowCarbonDTO.setCalorieNum((bikeCalorie + electricBikeCalorie) <= 0 ? 0 :
                new BigDecimal(bikeCalorie + electricBikeCalorie).setScale(2, RoundingMode.HALF_UP).doubleValue());
        log.info("bikeMileage:{},electricBikeMileage:{},lowCarbonDTO:{}",bikeMileage,electricBikeMileage, JSON.toJSON(lowCarbonDTO));
    }
}
